package com.toe.forum.webapi.service.impl;

import com.toe.common.exception.ToeServiceException;
import com.toe.common.pojo.domain.ToeAuthenticationInfo;
import com.toe.common.restful.StateEnum;
import com.toe.common.utils.IpUtils;
import com.toe.forum.service.ForumAlbumService;
import com.toe.forum.service.ForumUserLikeService;
import com.toe.forum.service.UserEnshrineArticleService;
import com.toe.forum.webapi.ESRepository.ArticleElasticsearchRepository;
import com.toe.common.censor.TextCensor;
import com.toe.forum.webapi.config.RabbitMQConfig;
import com.toe.forum.webapi.mapper.*;
import com.toe.forum.webapi.redisRepository.IArticleRedisRepository;
import com.toe.pojo.dto.forum.*;
import com.toe.pojo.entity.forum.ArticleElasticsearch;
import com.toe.pojo.entity.forum.ForumAlbum;
import com.toe.pojo.entity.forum.ForumArticle;
import com.toe.forum.service.ForumArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.toe.pojo.vo.forum.*;
import com.toe.pojo.vo.user.UserUserVO;
import com.toe.sso.service.IUserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.net.SocketException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;


/**
 * <p>
 * 文章表 服务实现类
 * </p>
 *
 * @author 陶涛
 * @since 2022-07-19
 */
@Service
@Slf4j
@DubboService
public class ForumArticleServiceImpl extends ServiceImpl<ForumArticleMapper, ForumArticle> implements ForumArticleService {
    @Autowired
    private ForumArticleMapper forumArticleMapper;

    @Autowired
    private ForumAlbumService forumAlbumService;

    @Autowired
    private ForumAlbumMapper forumAlbumMapper;

    @DubboReference
    private IUserInfoService dubboUserInfoService;

    @Autowired
    private IArticleRedisRepository redisRepository;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // RabbitTemplate就是amqp框架提供的发送消息的对象
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ForumReplyMapper forumReplyMapper;

    @Autowired
    private ForumUserLikeService forumUserLikeService;

    @Autowired
    private UserEnshrineArticleService userEnshrineArticleService;

    // 注入SpringData操作Es的持久层对象
    @Autowired
    private ArticleElasticsearchRepository repository;

    @Autowired
    private ForumRemarkMapper forumRemarkMapper;

    @Autowired
    private ForumUserLikeMapper forumUserLikeMapper;

    @Autowired
    private UserEnshrineArticleMapper userEnshrineArticleMapper;

    @Override
    public void prepareLoad() {
        log.info("清楚以前的老缓存");
        redisRepository.deleteAllItem();
        log.info("存入所有类别中综合排名前50的文章的详细数据");
        List<ArticleDetailVO> articleDetailVOS = selectAllArticlePage(1, 50);
        ArticleVO articleVO = new ArticleVO();
        for (ArticleDetailVO articleDetailVO:articleDetailVOS
        ) {
            BeanUtils.copyProperties(articleDetailVO,articleVO);
            redisRepository.save(articleVO);
        }
        log.info("所有类别中综合排名前50的文章的详细数据已经存入完成.");
        List<ArticleDetailVO> articleDetailVOS1 = selectAllArticle();
        for (ArticleDetailVO articleDetailVO:articleDetailVOS1
        ) {
            redisRepository.saveArticleLike(articleDetailVO.getId(),articleDetailVO.getLikeCount());
            redisRepository.saveArticleEnshrine(articleDetailVO.getId(),articleDetailVO.getEnshrineCount());
            redisRepository.savaArticleLook(articleDetailVO.getId(),articleDetailVO.getPageView());
        }
        log.info("所有文章的点赞数,收藏数已经加入缓存!!!!!!!!");
    }

    @Override
    public void insert(ArticleAddDTO articleAddDTO) {
        //不用判断文章是否重复,多个用户可以发CashPreLoad同一篇文章,一个用户也可以多次发同一篇文章
        log.info("开始处理添加文章业务!!!!");
        //发表文章的敏感字过滤
//        String message = articleAddDTO.getCoryWriting();
//        String violationReason = TextCensor.TextCensor(message);
//        if (violationReason!=null){
//            throw new ToeServiceException(StateEnum.ERR_FORUM_VIOLATION,violationReason);
//        }
        log.info("第一步插入文章信息:--------------------------");
        ForumArticle forumArticle = new ForumArticle();
        log.info("将同名属性categoryId,title,coryWriting复制到forumArticle中");
        BeanUtils.copyProperties(articleAddDTO,forumArticle);
        log.info("获取当前登录用户的信息");
        String s = TextCensor.TextCensor(forumArticle.getTitle());
        if (s!=null){
            throw new ToeServiceException(StateEnum.ERR_FORUM_VIOLATION,"不合规!");
        }
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        UserUserVO user = dubboUserInfoService.findUserById(userId);
        String nickname = user.getNickname();
        String avatar = user.getAvatar();
        log.info("向forumArticle中载入发表文章的人的信息");
        forumArticle.setAuthorId(userId);
        forumArticle.setAuthorNickname(nickname);
        forumArticle.setAvatar(avatar);
        log.info("初始化点赞量,浏览量,收藏量");
        forumArticle.setLikeCount(0l);
        forumArticle.setEnshrineCount(0l);
        forumArticle.setPageView(0l);
        log.info("初始化举报属性,2表示等待审核!!");
        forumArticle.setIsReport(2);
        LocalDateTime date = LocalDateTime.now();
        log.info("初始化,创建数据记录时间!!!|");
        forumArticle.setCreateTime(date);
        forumArticle.setUpdateTime(date);
        log.info("forumArticle信息载入完毕,向表中插入数据!!!");
        forumArticleMapper.insert(forumArticle);
        long articleId = forumArticle.getId();
        log.info("第二步插入文章图片信息:--------------------------");
        log.info("先从用户上传的数据中获取图片地址列表!-------------");
        List<String> urls = articleAddDTO.getUrls();
        log.info("--------------------{}",articleId);
        log.info("图片插入Album表中!!!!");
        ForumAlbum forumAlbum = new ForumAlbum();
        List<UrlVO> urls2 = new ArrayList<>();
        for (String url:urls
             ) {
            forumAlbum.setId(null);
            forumAlbum.setArticleId(articleId);
            forumAlbum.setUrl(url);
            forumAlbum.setCreateTime(date);
            forumAlbum.setUpdateTime(date);
            //添加图片
            forumAlbumMapper.insert(forumAlbum);
            UrlVO urlVO = new UrlVO();
            urlVO.setId(forumAlbum.getId());
            urlVO.setUrl(url);
            urls2.add(urlVO);
        }
        log.info("插入数据执行完毕!!!!");
//        //向Redis中插入数据
//        ArticleVO articleVO = new ArticleVO();
//        BeanUtils.copyProperties(forumArticle,articleVO);
//        articleVO.setUrls(urls2);
//        redisRepository.save(articleVO);
//        redisRepository.saveArticleLike(articleId,0l);
//        redisRepository.saveArticleEnshrine(articleId,0l);
//        redisRepository.savaArticleLook(articleId,0l);
        //向ES中插入数据
//        ArticleElasticsearch articleElasticsearch = new ArticleElasticsearch();
//        BeanUtils.copyProperties(forumArticle,articleElasticsearch);
//        repository.save(articleElasticsearch);
    }

    @Override
    public void deleteById(long id) {
        log.info("开始执行删除文章的业务!!!!!!");
        log.info("第一步Redis中是否有该文章信息:--------------------------");
        boolean exists = redisRepository.exists(id);
//        if (!exists){
//            throw new ToeServiceException(StateEnum.ERR_CLIENT,"该文章不存在!!!不能删除");
//        }
        //删除Redis中的数据
        redisRepository.deleteArticleById(id);
        redisRepository.deleteArticleLikeById(id);
        redisRepository.deleteArticleEnshrineById(id);
        redisRepository.deleteArticleLookById(id);
        log.info("Redis中已经删除完毕!!!!!!!!");
        /**
         * Redis中删除后接下来删除数据库中的数据
         */
        forumArticleMapper.deleteById(id);
        List<AlbumVO> albumVOS = forumAlbumService.selectAllAlbumByArticleId(id);
        for (AlbumVO a:albumVOS
             ) {
            forumAlbumService.deleteById(a.getId());
        }
        //删除ES中的数据
        repository.deleteById(id);
        log.info("数据库中的数据删除完毕!!!!!!!!!");
        //删除改文章的所有评论................
        forumRemarkMapper.deleteRemarkByArticleId(id);
        //删除所有的和此文章相关的收藏映射
        forumUserLikeMapper.deleteByArticleId(id);
        //删除所有的和此文章相关的点赞映射
        userEnshrineArticleMapper.deleteByArticleId(id);
        //删除所有的和此文章相关的回复
        forumReplyMapper.deleteByArticleId(id);
    }

    @Override
    public void updateArticle(ArticleUpdateDTO articleUpdateDTO) {
        log.info("开始执行文章更新业务!!!!!!!!");
        forumArticleMapper.updateArticle(articleUpdateDTO);
        /**
         * 更新完文章之后还需要更新相册
         */
        //表示用户新提交的数据
        List<String> urls = articleUpdateDTO.getUrls();
        //表示用户的原始的数据
        List<AlbumVO> albumVOS = forumAlbumService.selectAllAlbumByArticleId(articleUpdateDTO.getId());
        /**
         * 如果有的原始数据不包含在新数据中,删除那个原始数据,如果有新的数据不在原始数据中,应该加上新数据
         */
        AlbumAddDTO albumAddDTO = new AlbumAddDTO();
        for (int i = 0; i < urls.size(); i++) {
            if (albumVOS.contains(urls.get(i))){
                //表示此条数据用户未更改
                continue;
            }
            //不包含,说明是用户新加的图片要加到数据库中
            albumAddDTO.setArticleId(articleUpdateDTO.getId());
            albumAddDTO.setUrl(urls.get(i));
            forumAlbumService.insert(albumAddDTO);
        }
        for (int i = 0; i < albumVOS.size(); i++) {
            if (urls.contains(albumVOS.get(i).getUrl())){
                //表示此条数据用户未更改
                continue;
            }
            //表示用户已经不需要这张图片了,删除
            forumAlbumService.deleteById(albumVOS.get(i).getId());
        }
        /**
         * 数据库中修改完成,接下来应该修改Redis
         */
        long id = articleUpdateDTO.getId();
        ArticleDetailVO articleDetailVO = forumArticleMapper.selectArticleById(id);
        log.info("删除旧缓存!!!!");
        redisRepository.deleteArticleById(id);
        redisRepository.deleteArticleLookById(id);
        redisRepository.deleteArticleLikeById(id);
        redisRepository.deleteArticleEnshrineById(id);
        log.info("更新缓存!!!!!");
        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(articleDetailVO,articleVO);
        redisRepository.save(articleVO);
        redisRepository.savaArticleLook(id,articleDetailVO.getPageView());
        redisRepository.saveArticleLike(id,articleDetailVO.getLikeCount());
        redisRepository.saveArticleEnshrine(id,articleDetailVO.getEnshrineCount());
        log.info("更新ES!!!!!!!!!!");
        repository.deleteById(id);
        ArticleElasticsearch articleElasticsearch = new ArticleElasticsearch();
        BeanUtils.copyProperties(articleDetailVO,articleElasticsearch);
        repository.save(articleElasticsearch);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticle() {
        log.info("开始执行查询所有文章的业务!!!!!!!!!!");
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticle();
        return articleDetailVOS;
    }

    @Override
    public List<ArticleDetailVO> selectAllArticlePage(Integer pageNum, Integer pageSize) {
        log.info("开始执行分页查询所有文章的业务!!!!!!!!!!");
        List<ArticleSimpleVO> articleSimpleVOS = forumArticleMapper.selectAllArticlePage(pageNum, pageSize);
        List<ArticleDetailVO> articleDetailVOS = new ArrayList<>();
        return pageSelect(articleSimpleVOS,articleDetailVOS);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByCategoryId(long categoryId) {
        log.info("开始执行查询所有该分类的所有文章的业务!!!!!!!!!!");
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticleByCategoryId(categoryId);
        return articleDetailVOS;
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByCategoryIdPage(long categoryId, Integer pageNum, Integer pageSize) {
        log.info("开始执行分页查询对应分类id的所有文章的业务!!!!!!!!!!");
        List<ArticleSimpleVO> articleSimpleVOS = forumArticleMapper.selectAllArticleByCategoryIdPage(categoryId,pageNum, pageSize);
        List<ArticleDetailVO> articleDetailVOS = new ArrayList<>();
        return pageSelect(articleSimpleVOS,articleDetailVOS);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByAuthorId(long authorId) {
        log.info("开始执行查询对应分类作者id的所有文章的业务!!!!!!!!!!");
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticleByAuthorId(authorId);
        return articleDetailVOS;
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByAuthorIdPage(long authorId, Integer pageNum, Integer pageSize) {
        log.info("开始执行分页查询对应分类作者id的所有文章的业务!!!!!!!!!!");
        List<ArticleSimpleVO> articleSimpleVOS = forumArticleMapper.selectAllArticleByAuthorIdPage(authorId,pageNum, pageSize);
        List<ArticleDetailVO> articleDetailVOS = new ArrayList<>();
        return pageSelect(articleSimpleVOS,articleDetailVOS);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByUserLike() {
        log.info("开始执行查询当前用户所有点赞的文章!!!!!!!");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticleByUserLike(userId);
        return articleDetailVOS;
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByUserLikePage(Integer pageNum, Integer pageSize) {
        log.info("开始执行分页查询当前用户所有点赞的文章!!!!!!!");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        List<ArticleSimpleVO> articleSimpleVOS = forumArticleMapper.selectAllArticleByUserLikePage(userId, pageNum, pageSize);
        List<ArticleDetailVO> articleDetailVOS = new ArrayList<>();
        return pageSelect(articleSimpleVOS,articleDetailVOS);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByUserEnshrine() {
        log.info("开始执行查询当前用户所有收藏的文章!!!!!!!");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticleByUserEnshrine(userId);
        return articleDetailVOS;
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleByUserEnshrinePage(Integer pageNum, Integer pageSize) {
        log.info("开始执行分页查询当前用户所有收藏的文章!!!!!!!");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        List<ArticleSimpleVO> articleSimpleVOS = forumArticleMapper.selectAllArticleByUserEnshrinePage(userId, pageNum, pageSize);
        List<ArticleDetailVO> articleDetailVOS = new ArrayList<>();
        return pageSelect(articleSimpleVOS,articleDetailVOS);
    }

    @Override
    public List<ArticleDetailVO> selectAllArticleInCheck() {
        log.info("开始执行查询当前用户所有正在审核的文章!!!!!!!");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        List<ArticleDetailVO> articleDetailVOS = forumArticleMapper.selectAllArticleInCheck(userId);
        return articleDetailVOS;
    }

    @Override
    public ArticleDetailVO selectArticleById(long id) {
        log.info("开始查询具体文章的业务,先判断是否命中缓存!!!!!!!!!!");
        if (redisRepository.exists(id)){
            log.info("命中缓存!!!!!!!!!!!");
            ArticleVO articleVO = redisRepository.selectArticleById(id);
            long like_count = redisRepository.selectArticleLikeById(id);
            long enshrine_count = redisRepository.selectArticleEnshrineById(id);
            log.info("从缓存中取出了数据!!!!!!!");
            ArticleDetailVO articleDetailVO = new ArticleDetailVO();
            log.info("浏览量加一");
            String Lookkey = IArticleRedisRepository.KEY_ARTICLE_Look_PREFIX+id;
            long pageView = stringRedisTemplate.boundValueOps(Lookkey).increment();
            BeanUtils.copyProperties(articleVO,articleDetailVO);
            articleDetailVO.setLikeCount(like_count);
            articleDetailVO.setEnshrineCount(enshrine_count);
            articleDetailVO.setPageView(pageView);
            /**
             * 上面的操作只是将Redis中的浏览量+1,数据库的数据没有改变,使用RabbitMQ在空闲时间修改
             */
            // 更新信息收集完成,将消息发送给RabbitMQ
            ArticleUpdateCountDTO articleUpdateCountDTO = new ArticleUpdateCountDTO();
            articleUpdateCountDTO.setId(id);
            articleUpdateCountDTO.setPageView(pageView);
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.STOCK_EX,
                    RabbitMQConfig.STOCK_ROUT,
                    articleUpdateCountDTO);
            return articleDetailVO;
        }
        log.info("未命中缓存!!!,从数据库中获取数据!!!!!!!!");
        ArticleDetailVO articleDetailVO = forumArticleMapper.selectArticleById(id);
        if (articleDetailVO == null){
            //有可能是恶意访问,需要防止缓存穿透
            redisRepository.saveEmptyValue(id);
            return null;
        }
        //不是恶意访问,数据库中有数据,需要返回数据的同时,将此数据加入到缓存中
        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(articleDetailVO,articleVO);
        redisRepository.save(articleVO);
        redisRepository.saveArticleLike(id,articleDetailVO.getLikeCount());
        redisRepository.saveArticleEnshrine(id,articleDetailVO.getEnshrineCount());
        redisRepository.savaArticleLook(id,articleDetailVO.getPageView());
        return articleDetailVO;
    }

    @Override
    public void updateArticleIsReport(long id, Integer state) {
        log.info("开始执行更新文章状态的业务!!!!!!!!!!!(一般为用户举报文章)");
        ArticleReportUpdateDTO articleReportUpdateDTO = new ArticleReportUpdateDTO();
        articleReportUpdateDTO.setId(id);
        articleReportUpdateDTO.setState(state);
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,
                articleReportUpdateDTO);
    }

    @Override
    public void adminUpdateArticleIsReport(long id, Integer state) {
        log.info("开始执行更新文章状态的业务!!!!!!!!!!!(一般为管理员审核文章)");
        ArticleReportUpdateDTO articleReportUpdateDTO = new ArticleReportUpdateDTO();
        articleReportUpdateDTO.setId(id);
        articleReportUpdateDTO.setState(state);
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,
                articleReportUpdateDTO);
        if (state == 1){
            //举报核实,应该删除数据库的内容,调用此类的方法
            deleteById(id);
        }
    }

    @Override
    public void adminCheckArticlePass(long id) {
        log.info("将is_report改为0,正式发表");
        ArticleReportUpdateDTO articleReportUpdateDTO = new ArticleReportUpdateDTO();
        articleReportUpdateDTO.setId(id);
        articleReportUpdateDTO.setState(0);
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,
                articleReportUpdateDTO);
    }

    @Override
    public void adminCheckArticleFail(long id) {
        log.info("文章审核不通过,删除!!!!");
        deleteById(id);
    }

    @Override
    public void likeArticle(long articleId) {
        log.info("开始点赞业务");
        log.info("获取当前登录的用户的id");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        log.info("获取当前用户与对应id的点赞映射表");
        Boolean userLIkeVO = forumUserLikeService.selectOneUserLike(userId, articleId);
        ArticleUpdateCountDTO articleUpdateCountDTO = new ArticleUpdateCountDTO();
        if (!userLIkeVO){
            //表示该用户未点赞过这篇文章,可以进行点赞操作,反之进行取消点赞操作
            log.info("进行点赞操作!!!!!!!");
            String LikeKey = IArticleRedisRepository.KEY_ARTICLE_Like_PREFIX+articleId;
            Long LikeCount = stringRedisTemplate.boundValueOps(LikeKey).increment();
            articleUpdateCountDTO.setId(articleId);
            articleUpdateCountDTO.setLikeCount(LikeCount);
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.STOCK_EX,
                    RabbitMQConfig.STOCK_ROUT,
                    articleUpdateCountDTO);
            log.info("点赞操作完成,缓存和数据库都已更新!!!!!,接下来添加用户点赞映射表");
            UserLikeAddDTO userLikeAddDTO = new UserLikeAddDTO();
            userLikeAddDTO.setArticleId(articleId);
            userLikeAddDTO.setUserId(userId);
            forumUserLikeService.insert(userLikeAddDTO);
            return;
        }
        log.info("如果已经点赞过,那么应该进行的是取消点赞操作!!!!!!");
        String LikeKey = IArticleRedisRepository.KEY_ARTICLE_Like_PREFIX+articleId;
        Long LikeCount = stringRedisTemplate.boundValueOps(LikeKey).decrement(1);
        articleUpdateCountDTO.setId(articleId);
        articleUpdateCountDTO.setLikeCount(LikeCount);
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,
                articleUpdateCountDTO);
        log.info("取消点赞完成,数据库和Redis中都已更改!!!!!!!!!,接下来需要把点赞映射表删除");
        forumUserLikeService.deleteUserLike(userId,articleId);
        log.info("点赞业务完成!!!!!");
    }

    @Override
    public void enshrineArticle(long articleId) {
        log.info("开始收藏业务");
        log.info("获取当前登录的用户的id");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        log.info("获取当前用户与对应id的收藏映射表");
        EnshrineArticleVO enshrineArticleVO = userEnshrineArticleService.selectEnshrineById(userId, articleId);
        ArticleUpdateCountDTO articleUpdateCountDTO = new ArticleUpdateCountDTO();
        if (enshrineArticleVO == null){
            log.info("该用户未收藏过这篇文章");
            log.info("进行收藏操作!!!!!!!");
            String enshrineKey = IArticleRedisRepository.KEY_ARTICLE_Enshrine_PREFIX+articleId;
            Long enshrineCount = stringRedisTemplate.boundValueOps(enshrineKey).increment();
            articleUpdateCountDTO.setId(articleId);
            articleUpdateCountDTO.setEnshrineCount(enshrineCount);
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.STOCK_EX,
                    RabbitMQConfig.STOCK_ROUT,
                    articleUpdateCountDTO);
            log.info("收藏完成,数据库和Redis中都已更改!!!!!!!!!,接下来需要把收藏映射表加上");
            EnshrineArticleAddDTO enshrineArticleAddDTO = new EnshrineArticleAddDTO();
            enshrineArticleAddDTO.setArticleId(articleId);
            enshrineArticleAddDTO.setUserId(userId);
            userEnshrineArticleService.insert(enshrineArticleAddDTO);
            log.info("收藏业务完成!!!!!");
            return;
        }
        log.info("该用户收藏记录已经存在应该进行取消收藏操作!!!!!!!!!!!");
        String enshrineKey = IArticleRedisRepository.KEY_ARTICLE_Enshrine_PREFIX+articleId;
        Long enshrineCount = stringRedisTemplate.boundValueOps(enshrineKey).decrement(1);
        articleUpdateCountDTO.setId(articleId);
        articleUpdateCountDTO.setEnshrineCount(enshrineCount);
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.STOCK_EX,
                RabbitMQConfig.STOCK_ROUT,
                articleUpdateCountDTO);
        log.info("取消收藏的数据库和Redis都已经更新完毕!!!,接下来需要删除收藏映射表");
        userEnshrineArticleService.delete(userId,articleId);
        log.info("收藏业务完成!!!!!!");
    }

    @Override
    public int selectCurrentLikeCount() {
        log.info("开始执行查询当前用户的所有点赞文章数量");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        int count = forumArticleMapper.selectCurrentLikeCount(userId);
        return count;
    }

    @Override
    public int selectCurrentEnshrineCount() {
        log.info("开始执行查询当前用户的所有收藏文章数量");
        Object credentials = SecurityContextHolder.getContext().getAuthentication().getCredentials();
        ToeAuthenticationInfo authenticationInfo = (ToeAuthenticationInfo)credentials;
        Long userId = authenticationInfo.getId();
        int count = forumArticleMapper.selectCurrentEnshrineCount(userId);
        return count;
    }

    @Override
    public void deleteArticleByIds(Long... ids) {
        forumArticleMapper.deleteArticleByIds(ids);
        forumAlbumMapper.deleteAlbumByIds(ids);
    }

    /**
     * 代码复用
     * @param articleSimpleVOS
     * @param articleDetailVOS
     * @return
     */
    public List<ArticleDetailVO> pageSelect(List<ArticleSimpleVO> articleSimpleVOS,List<ArticleDetailVO> articleDetailVOS){
        for (int i = 0; i < articleSimpleVOS.size(); i++) {
            ArticleDetailVO articleDetailVO = new ArticleDetailVO();
            BeanUtils.copyProperties(articleSimpleVOS.get(i),articleDetailVO);
            long id = articleSimpleVOS.get(i).getId();
            List<AlbumVO> albumVOS = forumAlbumService.selectAllAlbumByArticleId(id);
            List<UrlVO> urls = new ArrayList<>();
            for (int j = 0; j < albumVOS.size(); j++) {
                UrlVO urlVO = new UrlVO();
                urlVO.setId(albumVOS.get(j).getId());
                urlVO.setUrl(albumVOS.get(j).getUrl());
                urls.add(urlVO);
            }
            articleDetailVO.setUrls(urls);
            articleDetailVOS.add(articleDetailVO);
        }
        return articleDetailVOS;
    }

//    public List<ArticleDetailVO> parseUrl(List<ArticleDetailVO> list){
//        try {
//            String localIp = IpUtils.getLocalIp();
//            String first = "http://"+localIp+":10003/";
//            for (int i = 0; i < list.size(); i++) {
//                for
//            }
//        } catch (SocketException e) {
//            e.printStackTrace();
//        }
//        return list;
//    }
}
